package mylittleinvestigations;

import java.awt.FontFormatException;
import java.awt.Toolkit;
import java.awt.font.TextAttribute;
import java.io.IOException;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import mylittleinvestigations.CaseInformation.Case;
import mylittleinvestigations.GameUi.GameUiLoader;
import mylittleinvestigations.Screens.GameScreen;
import mylittleinvestigations.Screens.Screen;
import mylittleinvestigations.Screens.TitleScreen;
import org.dawnmew.jpurewave.SoundSystem;
import org.dawnmew.jvirtualstream.EmbeddedFileSystemSource;
import org.dawnmew.jvirtualstream.VirtualFileSystem;
import org.lwjgl.LWJGLException;
import org.newdawn.slick.*;

public class Game extends BasicGame
{
    public Game(String title)
    {
        super(title);
    }
    
    private HashMap<String, Screen> screenFromIdHashMap;
    private Screen currentScreen;
    
    private String[] sfxIdList =
    {
        "ButtonClick1",
        "ButtonClick2",
        "ButtonClick3",
        "ButtonClick4",
        "LetterBlip",
        "NewAddition",
        "NewPartner",
    };

    public void init(GameContainer gc) throws SlickException
    {   
        VirtualFileSystem.getInstance().addSource("EmbedFileSystem", new EmbeddedFileSystemSource());
        
        SoundSystem.getInstance().init();
        SoundSystem.getInstance().setVolumeSound(0.8f);
        SoundSystem.getInstance().setVolumeMusic(0.9f);

        MouseHelper.Initialize();

        for (int i = 0; i < sfxIdList.length; i++)
        {
            SoundSystem.getInstance().loadSound(sfxIdList[i], "SFX/" + sfxIdList[i]);
        }

        this.screenFromIdHashMap = new HashMap<String, Screen>();

        this.screenFromIdHashMap.put(TitleScreen.Id, new TitleScreen());
        this.screenFromIdHashMap.put(GameScreen.Id, new GameScreen());

        this.currentScreen = this.screenFromIdHashMap.get(TitleScreen.Id);
        this.currentScreen.Init();
            
        try
        {
            HashMap fayesAttributes = new HashMap();
            fayesAttributes.put(TextAttribute.KERNING, TextAttribute.KERNING_ON);
            fayesAttributes.put(TextAttribute.TRACKING, 0.03);
            java.awt.Font fayesMousewritingFont = java.awt.Font.createFont(java.awt.Font.TRUETYPE_FONT, VirtualFileSystem.getInstance().getInputStream("fonts/FayesMousewriting_quotemapped.ttf")).deriveFont(fayesAttributes);
            
            GameUiLoader.getInstance().dialogFont = Utils.getUnicodeFont(fayesMousewritingFont, 37, true, false);
            GameUiLoader.getInstance().evidenceSelectorFont = Utils.getUnicodeFont(fayesMousewritingFont, 24, true, false);
            GameUiLoader.getInstance().partnerInformationFont = Utils.getUnicodeFont(fayesMousewritingFont, 14, true, false);

            java.awt.Font celestiaMediumFont = java.awt.Font.createFont(java.awt.Font.TRUETYPE_FONT, VirtualFileSystem.getInstance().getInputStream("fonts/CelestiaMediumRedux1.5.ttf"));

            GameUiLoader.getInstance().confrontationNumberingFont = Utils.getUnicodeFont(celestiaMediumFont, 100, false, false);
            GameUiLoader.getInstance().tabFont = Utils.getUnicodeFont(celestiaMediumFont, 22, false, false);
                
            if (Settings.isMac)
            {
                com.apple.eawt.Application application = com.apple.eawt.Application.getApplication();
                application.setDockIconImage(Toolkit.getDefaultToolkit().createImage(Game.class.getClassLoader().getResource("embed-data/image/Logo.png")));
            }
        }
        catch (FontFormatException ex)
        {
            Logger.getLogger(Game.class.getName()).log(Level.SEVERE, null, ex);
        }
        catch (IOException ex)
        {
            Logger.getLogger(Game.class.getName()).log(Level.SEVERE, null, ex);
        }
            
        GameUiLoader.getInstance().LoadUi();
    }
    
    public void update(GameContainer gc, int delta) throws SlickException
    {
        Debug.StartTimingOperation("Update loop");
        Case.getInstance().getAudioManager().Update(gc, delta);
        
        if (this.currentScreen != null)
        {
            this.currentScreen.Update(gc, delta);
            
            if (this.currentScreen.getIsFinished())
            {
                String nextScreenId = this.currentScreen.getNextScreenId();
                
                if (nextScreenId == null)
                {
                    gc.exit();
                }
                else if (this.screenFromIdHashMap.containsKey(nextScreenId))
                {
                    this.currentScreen = this.screenFromIdHashMap.get(nextScreenId);
                    this.currentScreen.Init();
                }
                else
                {
                    throw new IllegalArgumentException("Unknown screen ID: '" + nextScreenId + "'.");
                }
            }
        }
        Debug.ReportTimeElapsed();
    }

    public void render(GameContainer gc, Graphics g) throws SlickException
    {
        Debug.StartTimingOperation("Render loop");
        if (this.currentScreen != null)
        {
            this.currentScreen.Draw(gc, g);
        }
        Debug.ReportTimeElapsed();
    }

    public static void main(String[] args) throws SlickException
    {
        Thread.currentThread().setPriority(7);
        
        int frameRate = 60;
        
        for(String arg : args)
        {
            String argLower = arg.toLowerCase();
            if("-disablesharedcontext".equals(argLower))
            {
                Settings.UseSharedContext = false;
                System.out.println("OpenGL shared contexts disabled by commandline argument.");
            }else if(argLower.startsWith("-fps")&&argLower.length()>4)
            {
                Integer testConvert = Integer.valueOf(argLower.substring(4));
                if(testConvert>0)
                    frameRate = testConvert.intValue();
                else
                    System.out.println("Invalid FPS limit ignored: "+argLower.substring(4));
            }
            
        }
        if(Settings.UseSharedContext)
            try
            {
                GameContainer.enableSharedContext();
            }catch(Exception ex)
            {
                Settings.UseSharedContext = false;
            }
        
        Game game = new Game(Settings.GameTitle);
        
        //RenderThread.getInstance().Init(game, (int)Settings.DisplayBounds.getX(), (int)Settings.DisplayBounds.getY());
        //InputThread.getInstance().Init((int)Settings.DisplayBounds.getY());
        
        AppGameContainer app = new AppGameContainer(game, (int)Settings.DisplayBounds.getX(), (int)Settings.DisplayBounds.getY(), false /* fullscreen */); //Creates and titles window.
        app.setIcons(new String[] { "embed-data/image/Logo16.png", "embed-data/image/Logo32.png" });
        app.setSmoothDeltas(false); //Ignore for now.
        app.setUpdateOnlyWhenVisible(false); //Slick does something really stupid if you don't set this.
        app.setAlwaysRender(true); //Ditto.
        app.setTargetFrameRate(frameRate); //Tries to stick close to a certain FPS, but not quite exact.
        app.setShowFPS(Debug.ShowFps); //Debug only, basic FPS clock in top-left corner.
        app.start(); //Up and away!
    }
}
